home *** CD-ROM | disk | FTP | other *** search
/ Best Tools for JAVA / Best Tools for JAVA.iso / JAVA_ALL / IDE / SUBARTIC / SUB_ARCT / OUTPUT / PPM_TO_C.JAV < prev    next >
Encoding:
Text File  |  1996-10-04  |  10.1 KB  |  331 lines

  1.  
  2. package sub_arctic.output;
  3.  
  4. import java.io.DataInputStream;
  5. import java.io.IOException;
  6. import java.io.EOFException;
  7. import java.util.StringTokenizer;
  8.  
  9. /** 
  10.  * A small stand-alone program to do a translation from PPM format image 
  11.  * files to code for statically initializing an in memory loaded_image object.
  12.  * The result of this program is code for five static declarations -- an 
  13.  * integer for the width of the image, an integer for the height, array of 
  14.  * integers for the RGB values, a static loaded_image, and an accessor 
  15.  * function for the image.  These entities are declared as <name>_width, 
  16.  * <name>_height, <name>_data, _<name> and <name>(), where <name> is the 
  17.  * string supplied by the -name command line argument (or the default of 
  18.  * "image"). <p>
  19.  *
  20.  * Each element of the static array encodes the value for one 
  21.  * pixel in the form 0xaarrggbb, where aa is the hex value for alpha 
  22.  * (transparency) rr for red, etc.  Currently all alpha values are set to 
  23.  * ff (fully opaque). <p>
  24.  *
  25.  * The program can be invoked from the command line using the -name argument
  26.  * to control the declared names.  Reads a PPM file from standard input,
  27.  * and produces the resulting declarations on standard output.<p>
  28.  *
  29.  * This program now handles both ASCII and Binary encoded PPM files.
  30.  *
  31.  * @author Scott Hudson
  32.  */
  33. public class ppm_to_code {
  34.  
  35.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  36.  
  37.   /** No instances of this class */
  38.   private ppm_to_code() {}
  39.  
  40.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  41.  
  42.   /** The input stream we are reading from (this will get wrapped around 
  43.    *  System.in).
  44.    */
  45.   protected static DataInputStream input_file = null;
  46.  
  47.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  48.  
  49.   /** A tokenizer attached to the string for the current line */
  50.   protected static StringTokenizer current_line = null;
  51.  
  52.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  53.  
  54.   /** Get the next white-space delimited token from the input file */
  55.   protected static String next_token()
  56.     {
  57.       String line, tkn;
  58.  
  59.       /* loop to repeat when we get blank and comment lines */
  60.       for (;;)
  61.     {
  62.           /* init the input stream to standard input if we haven't done that */
  63.           if (input_file == null) 
  64.         input_file = new DataInputStream(System.in);
  65.  
  66.           /* if there is no current line, or its exhausted get a new one */
  67.           if (current_line == null || !current_line.hasMoreTokens())
  68.         {
  69.           /* read another line */
  70.           try {
  71.             line = input_file.readLine();
  72.           } catch (IOException ex) {
  73.             /* for now treat error as EOF */
  74.             line = null;
  75.           }
  76.  
  77.           /* build a tokenizer around it */
  78.           if (line != null)
  79.             current_line = new StringTokenizer(line);
  80.  
  81.           /* if there are no tokens in the line, skip it */
  82.           if (current_line.countTokens() == 0)
  83.         {
  84.           current_line = null;
  85.           continue;
  86.         }
  87.         }
  88.  
  89.           /* if we have failed to construct a current line we are at the end */
  90.           if (current_line == null) return null;
  91.  
  92.       /* pull out the next token */
  93.       tkn = current_line.nextToken();
  94.  
  95.       /* if it starts with #, skip the rest of the line and go to next */
  96.       if (tkn.startsWith("#"))
  97.         {
  98.           current_line = null;
  99.           continue;
  100.         }
  101.  
  102.           /* otherwise we return the token */
  103.           return tkn;
  104.     }
  105.     }
  106.  
  107.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  108.  
  109.   /** Get the next token from standard input and try to interpret it as a 
  110.    *  decimal integer.  If this fails we print the given message on System.err
  111.    *  and exit.
  112.    *
  113.    * @param String message error message to print on System.err if we fail.
  114.    * @return int integer value of next token treated as a decimal integer.
  115.    */
  116.   protected static int next_int(String message)
  117.     {
  118.        String tkn;
  119.  
  120.        /* get the next token and try to make an integer value out of it */
  121.        tkn = next_token();
  122.        try {
  123.          return (new Integer(tkn)).intValue();
  124.        } catch (NumberFormatException ex) {
  125.       System.err.println(message + " -- giving up.");
  126.       System.exit(2);
  127.       return 0;
  128.        }
  129.     }
  130.  
  131.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  132.  
  133.   /** 
  134.    * Write a color out to standard input encoded in a 32 bit hex constant (we 
  135.    * use longs here so everything will be unsigned.  The result will be in the
  136.    * form "0xaarrggbb".
  137.    *
  138.    * @param long alpha transparency value.
  139.    * @param long r     red value.
  140.    * @param long g     green value.
  141.    * @param long b     blue value.
  142.    */
  143.   protected static void write_hex_color(long alpha, long r, long g, long b)
  144.     {
  145.       long encoding = ((alpha&0xff) << 24) | ((r&0xff) << 16) | 
  146.               ((g&0xff) << 8)      | (b&0xff);
  147.       System.out.print("0x" + Long.toString(encoding,16));
  148.     }
  149.  
  150.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  151.  
  152.   /** Print a "usage" message and exit */
  153.   protected static void usage()
  154.     {
  155.       System.out.println("Usage: java sub_arctic.output.ppm_to_code " + 
  156.              "[-name varname] < input.ppm > output"); 
  157.       System.exit(3);
  158.     }
  159.  
  160.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  161.  
  162.   /** 
  163.    * Main program so we can be invoked from the command line. 
  164.    * @param String argv[] arguments passed from the command line.
  165.    */
  166.   public static void main(String argv[]) 
  167.     {
  168.       String tkn;
  169.       int    i,w,h,max_color,r,g,b,len;
  170.       int    alpha = 0xff;
  171.       int    cnt   = 0;
  172.       String name = "image";
  173.       boolean is_binary = false;
  174.  
  175.       /* parse argument(s) */
  176.       len = argv.length;
  177.       for (i=0; i<len; i++)
  178.     {
  179.       if (argv[i].equalsIgnoreCase("-name"))
  180.         {
  181.           if (++i>=len || argv[i].startsWith("-"))
  182.         usage();
  183.           else
  184.         name = argv[i];
  185.         }
  186.       else
  187.         usage();
  188.     }
  189.  
  190.       /* we expect a "P3" first */
  191.       tkn = next_token();
  192.       if (!tkn.equalsIgnoreCase("p3"))
  193.     {
  194.       if (tkn.equalsIgnoreCase("p6"))
  195.         {
  196.           is_binary = true;
  197.         }
  198.       else
  199.         {
  200.            System.err.println(
  201.            "Didn't find PPM magic number (\"P3\" or \"P6\") at head " + 
  202.                "of file -- giving up");
  203.            System.exit(1);
  204.         }
  205.     }
  206.  
  207.        /* then width, height, and max_color and decimal constants */ 
  208.        w = next_int("Didn't find width");
  209.        h = next_int("Didn't find height");
  210.        max_color = next_int("Didn't find max_color");
  211.  
  212.       /* put out start of output */
  213.       System.out.println("  // (generated from ppm file)");
  214.       System.out.println("  protected static int "+name+"_width = " + w + ";");
  215.       System.out.println("  protected static int "+name+"_height = " + h + ";");
  216.       System.out.println("  protected static int[] "+ name+"_data = {");
  217.  
  218.       /* start indented line */
  219.       System.out.print("    ");
  220.  
  221.       /* if we have binary data, do that separately */
  222.       if (is_binary)
  223.     {
  224.       do_binary_data(w,h);
  225.     }
  226.       else
  227.     {
  228.           /* read the body of the data in ASCII */
  229.           for (i=0; i<w*h; i++)
  230.         {
  231.           /* get the RGB components */
  232.           r = next_int("Incomplete color code or short file");
  233.           g = next_int("Incomplete color code or short file");
  234.           b = next_int("Incomplete color code or short file");
  235.     
  236.           /* write out the color */
  237.           write_hex_color(alpha,r,g,b);
  238.           System.out.print(",");
  239.           cnt++;
  240.  
  241.           /* end the line and start another if we are getting too long */
  242.           if (cnt == 6)
  243.             {
  244.               System.out.println();
  245.               System.out.print("    ");
  246.               cnt = 0;
  247.             }
  248.         }
  249.     }
  250.  
  251.       /* close out the initializer */
  252.       System.out.println("};");
  253.  
  254.       /* do the rest of the code */
  255.       System.out.println("  protected static sub_arctic.output.loaded_image _" +
  256.                 name + " = null;");
  257.       System.out.println();
  258.       System.out.println("  public static sub_arctic.output.loaded_image " + 
  259.                 name + "() {");
  260.       System.out.println("    if (_" + name + " == null)");
  261.       System.out.println("      _"+name+" = new sub_arctic.output.loaded_image("
  262.                      +name+"_data,");
  263.       System.out.println("           "+name+"_width,"+name+"_height);");
  264.       System.out.println("    return _"+name+";");
  265.       System.out.println("  }");
  266.     }
  267.  
  268.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  269.  
  270.   /** 
  271.    * Process binary coded data body.  We expect to see 3*w*h bytes of data
  272.    * each representing a color value.  We write out initialization code based
  273.    * on this data.
  274.    * @param int w width of image.
  275.    * @param int h height of image.
  276.    */
  277.    protected static void do_binary_data(int w, int h)
  278.      {
  279.        byte data[] = new byte[w*h*3];
  280.        int i,r,g,b;
  281.        int cnt = 0;
  282.  
  283.        /* read the whole thing */
  284.        try {
  285.      input_file.readFully(data); 
  286.        } catch (EOFException eof) {
  287.      System.err.println("WARNING: Premature EOF while reading binary data" +                            " -- writing truncated image");
  288.        } catch (IOException ex) {
  289.      System.err.println("An IO error has occured while reading " + 
  290.                 "binary data -- giving up");
  291.          System.exit(2);
  292.        }
  293.  
  294.       /* write the init code */
  295.       for (i = 0; i < w*h*3;)
  296.     {
  297.       /* write one pixel */
  298.       r = data[i++]; g = data[i++]; b = data[i++]; 
  299.       write_hex_color(0xff, r,g,b);
  300.       System.out.print(",");
  301.       cnt++;
  302.  
  303.       /* end the line and start another if we are getting too long */
  304.       if (cnt == 6)
  305.         {
  306.           System.out.println();
  307.           System.out.print("    ");
  308.           cnt = 0;
  309.         }
  310.     }
  311.      }
  312.  
  313.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  314. }
  315. /*=========================== COPYRIGHT NOTICE ===========================
  316.  
  317. This file is part of the subArctic user interface toolkit.
  318.  
  319. Copyright (c) 1996 Scott Hudson and Ian Smith
  320. All rights reserved.
  321.  
  322. The subArctic system is freely available for most uses under the terms
  323. and conditions described in 
  324.   http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html 
  325. and appearing in full in the lib/interactor.java source file.
  326.  
  327. The current release and additional information about this software can be 
  328. found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
  329.  
  330. ========================================================================*/
  331.